package org.tinygroup.dbrouterjdbc3.jdbc;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.tinygroup.commons.tools.CollectionUtil;
import org.tinygroup.commons.tools.StringUtil;
import org.tinygroup.dbrouter.config.Shard;
import org.tinygroup.dbrouter.config.TableMapping;

/**
 * 根据sql的正则规范，把%转换成.*,然后查询出router下匹配的shard。
 * 
 * @author renhui
 * 
 */
public class ShardsFilter {

	private List<Shard> ableShards;

	public ShardsFilter(List<Shard> ableShards) {
		super();
		this.ableShards = ableShards;
	}

	public static boolean isMatch(String namePattern, String name) {
		Pattern pattern = getMatchPattern(namePattern);
		return pattern.matcher(name).matches();
	}

	private static Pattern getMatchPattern(String namePattern) {
		String newPattern = namePattern;
		if (StringUtil.isBlank(newPattern)) {
			newPattern = ".*";
		}
		Pattern pattern = Pattern.compile(StringUtil.replaceAll(newPattern,
				"%", ".*"));
		return pattern;
	}

	public List<ShardFilterData> filter(String namePattern) {
		Pattern pattern = getMatchPattern(namePattern);
		List<ShardFilterData> datas = new ArrayList<ShardFilterData>();
		if (!CollectionUtil.isEmpty(ableShards)) {
			for (Shard shard : ableShards) {
				List<TableMapping> tableMappings = shard.getTableMappings();
				ShardFilterData data = getMatchName(pattern, tableMappings);
				if (data != null) {
					datas.add(data);
				}
			}
		}
		return datas;
	}

	public String getPhysicsTableName(String logicTableName) {
		if (!CollectionUtil.isEmpty(ableShards)) {
			for (Shard shard : ableShards) {
				List<TableMapping> tableMappings = shard.getTableMappings();
				if (!CollectionUtil.isEmpty(tableMappings)) {
					for (TableMapping tableMapping : tableMappings) {
						if (logicTableName.equals(tableMapping.getTableName())) {
							return tableMapping.getShardTableName();
						}
					}
				}
			}
		}
		return null;
	}

	private ShardFilterData getMatchName(Pattern pattern,
			List<TableMapping> tableMappings) {
		if (!CollectionUtil.isEmpty(tableMappings)) {
			ShardFilterData data = new ShardFilterData();
			for (TableMapping tableMapping : tableMappings) {
				if (pattern.matcher(tableMapping.getTableName()).matches()) {
					data.put(tableMapping.getShardTableName(),
							tableMapping.getTableName());
					data.setPhysicsSchema(tableMapping.getPhysicsSchema());
					data.setPhysicsCatalog(tableMapping.getPhysicsCatalog());
				}
			}
			return data;
		}
		return null;
	}

	public class ShardFilterData {

		private Map<String, String> mapping = new HashMap<String, String>();

		private String physicsSchema;
		private String physicsCatalog;

		public ShardFilterData() {
		}

		public void put(String key, String value) {
			mapping.put(key, value);
		}

		public String get(String key) {
			return mapping.get(key);
		}

		public boolean containKey(String key) {
			return mapping.containsKey(key);
		}

		public String getPhysicsSchema() {
			return physicsSchema;
		}

		public void setPhysicsSchema(String physicsSchema) {
			this.physicsSchema = physicsSchema;
		}

		public String getPhysicsCatalog() {
			return physicsCatalog;
		}

		public void setPhysicsCatalog(String physicsCatalog) {
			this.physicsCatalog = physicsCatalog;
		}

	}

}
